﻿using Newtonsoft.Json.Linq;
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.Net.Http;
using System.Text;
using T.FAS.Runtime.Metadata.Entity.Page;
using System.Linq;
using T.FAS.Runtime.Metadata.Entity.DataModel;
//using T.FAS.MetaData.Dev.Client;
using T.FAS.Runtime.DataModel.Dao;
using T.FAS.Page.MetaData.Dao.Teable;
using static T.FAS.Runtime.Metadata.Entity.DataModel.CompositeDataObjectRefSchemaEntity;

namespace T.FAS.Runtime.Metadata.Plugin
{
    internal class PageControlRTPService
    {
        public void PublishTeable(PageMetaData pageMetaData)
        {
            if(pageMetaData.ExtProperties != null 
                && pageMetaData.ExtProperties.ContainsKey("hasTeable") 
                && !string.IsNullOrEmpty(pageMetaData.ExtProperties["hasTeable"].PropValue)) {
                PageUIControl teableControl = GetTeableControl(pageMetaData.PCUIDom.Controls);
                if (teableControl != null)
                {
                    var options = JsonConvert.DeserializeObject<Dictionary<string, object>>(teableControl.Options);
                    Dictionary<string, object> formData = new Dictionary<string, object>();
                    formData.Add("name", pageMetaData.Name);
                    formData.Add("dbTableName", pageMetaData.Code);
                    formData.Add("description", pageMetaData.Name);
                    formData.Add("fields", new List<object>());
                    formData.Add("views", new List<object>());
                    formData.Add("records", new List<object>());
                    formData.Add("order", 0);
                    formData.Add("fieldKeyType", "id");
                    formData.Add("icon", "📈");
                    MultiDimensionTableUtil teableUtil = new MultiDimensionTableUtil();
                    bool useCDO = false;
                    if (options.ContainsKey("useCDO")) useCDO = (bool)options["useCDO"];
                    if (useCDO && options.ContainsKey("cDO"))
                    {
                        string cdoCode = (string)options["cDO"];
                        var metaClientServie = MetaDataDevClientService.GetInstance();
                        var cdoMeta = metaClientServie.GetMetaData(cdoCode, pageMetaData.ProjectBranchID);
                        if (cdoMeta != null && cdoMeta.Content != null)
                        {
                            ColorTool colorTool = new ColorTool();
                            CompositeDataObject compositeData = cdoMeta.Content as CompositeDataObject;
                            var compositeNodeObject = compositeData.CompositeNodeObjects.FirstOrDefault();
                            DataObject dataObject = compositeNodeObject.DataObject;
                            DatabaseConfig baseConfig = new DatabaseLogic().GetDatabaseConfigs(new Dictionary<string, string> { { "ID", dataObject?.DatabaseID } }).FirstOrDefault();
                            List<CNOElement> elements = null;
                            if (options.ContainsKey("filterFields"))
                            {
                                JArray elementArr = (JArray)options["filterFields"];
                                elements = elementArr.Children<JObject>()
                                 .Select(jObj => jObj.ToObject<CNOElement>())
                                 .ToList();
                            }
                            else
                            {
                                elements = compositeNodeObject.Elements.Cast<CNOElement>().ToList();
                            }
                            var associations = compositeNodeObject.Associations;
                            var list = new List<Dictionary<string, object>>();
                            elements.ForEach(element => {
                                if (excludeColumns.Contains(element.Name)) return;
                                if (element.DataColumn == null) return;
                                string fieldName = element.Alias.ToLower();
                                string fieldType = "";
                                Dictionary<string, object> fieldOptions = null;
                                if (element.filter_inputWay == "down" && element.filter_dataType == "fixed")
                                {
                                    fieldOptions = HandleSelectOption(element.filter_dataValue, colorTool);
                                    fieldType = "singleSelect";
                                }
                                else if (element.filter_dataType == "action")
                                {                                    
                                    if (element.filter_inputWay == "down") fieldType = "singleSelect";
                                    if (element.filter_inputWay == "help") fieldType = "selectHelper";
                                    else if (element.filter_inputWay == "treehelp") fieldType = "treeSelectHelper";
                                }
                                else if (associations != null)
                                {
                                    var elementAssociation = associations.Find(association => association.Items.Find(item => item.SourceElementID == element.ID) != null);
                                    if (elementAssociation != null)
                                    {
                                        fieldType = "singleSelect";
                                    }
                                }
                                var teableType = teableUtil.GetTeableFieldType(element.DataColumn, null, fieldType);
                                var teableField = teableUtil.GetField(fieldName, element.DisplayName, teableType);
                                if (fieldOptions != null)
                                {
                                    teableField["options"] = fieldOptions;
                                }
                                list.Add(teableField);
                            });
                            formData["fields"] = list;
                            formData["dbTableName"] = dataObject?.LogicTableName.ToLower();
                            formData["description"] = dataObject?.Name;
                            formData.Add("connectionString", baseConfig?.ConfigKey);                            
                        }
                    }
                    else if (useCDO && options.ContainsKey("dataSource"))
                    {
                        JObject dataSourceObject = (JObject)options["dataSource"];
                        var dataSourceType = dataSourceObject.Value<string>("DataSourceType");

                        if (dataSourceType == "Action")
                        {
                            string dataBind = dataSourceObject.Value<string>("DataBind");
                            string dataSourceID = dataSourceObject.Value<string>("DataSource");

                            var dataSourceMeta = MetaDataDevClientService.GetInstance().GetMetaData(dataSourceID, pageMetaData.ProjectBranchID);
                            if (dataSourceMeta != null && dataBind.StartsWith("DataQuery") && dataSourceMeta.Content != null)
                            {
                                DataQuery dataQuery = dataSourceMeta.Content as DataQuery;
                                List<DataQueryColumn> dataQueryColumns = dataQuery.DataQueryColumns;
                                DataQuerySource mainDataSource = dataQuery.DataQuerySources.FirstOrDefault(ds => ds.IsMainSource);
                                DataObject dataObject = mainDataSource.DataObject;
                                DatabaseConfig baseConfig = new DatabaseLogic().GetDatabaseConfigs(new Dictionary<string, string> { { "ID", dataObject?.DatabaseID } }).FirstOrDefault();
                                List<DataColumn> dataColumns = dataObject.Columns;
                                var list = new List<Dictionary<string, object>>();
                                dataQueryColumns.Where(item => !excludeColumns.Contains(item.Name)).ToList().ForEach(dataQueryColumn =>
                                {
                                    DataColumn dataColumn = dataColumns.Find(dc => dc.ID == dataQueryColumn.DataObjectColumnID);
                                    var teableType = teableUtil.GetTeableFieldType(dataColumn, dataQueryColumn);
                                    string fieldName = dataQueryColumn.Alias.ToLower();
                                    list.Add(teableUtil.GetField(fieldName, dataQueryColumn.DisplayName, teableType));
                                });
                                formData["fields"] = list;
                                formData["dbTableName"] = dataObject?.LogicTableName.ToLower();
                                formData["description"] = dataObject?.Name;
                                formData.Add("connectionString", baseConfig?.ConfigKey);
                            }
                        }
                    }
                    else if (useCDO == false && options.ContainsKey("dataBase"))
                    {
                        JObject dataBase = (JObject)options["dataBase"];
                        DatabaseConfig baseConfig = new DatabaseLogic().GetDatabaseConfigs(new Dictionary<string, string> { { "ID", (string)dataBase["DataSourceID"] } }).FirstOrDefault();
                        formData["fields"] = teableUtil.InitFormDataColumns();
                        formData.Add("connectionString", baseConfig?.ConfigKey);                        
                    }
                    if (formData.ContainsKey("connectionString"))
                    {
                        var resultDic = teableUtil.PostTeable(formData, null);
                    }
                    
                }
            }
        }
        private PageUIControl GetTeableControl(List<PageUIControl> controls)
        {
            var teableControl = controls.Find(pageUI => pageUI.CtrlType == "");
            if (teableControl != null) return teableControl;
            controls.ForEach(control =>
            {
                if (control.Children != null && control.Children.Count > 0)
                {
                    var childControl = GetTeableControl(control.Children);
                    if (childControl != null)
                    {
                        teableControl = childControl;
                        return;
                    }
                }
            });
            return teableControl;
        }
        private List<string> excludeColumns = new List<string>() {
            "ID","Creator","CreateTime","LastModifier","LastModifyTime"
        };
        private Dictionary<string, object> HandleSelectOption(string filterDataValue, ColorTool colorTool)
        {
            StringBuilder optionsSB = new StringBuilder();
            Dictionary<string, object> optionDic = new Dictionary<string, object>();
            List<Dictionary<string, string>> choices = new List<Dictionary<string, string>>();
            string[] options = filterDataValue.Split(',');
            int index = 0;
            int count = options.Length;
            var colors = colorTool.GetUnrelatedColors(count);
            foreach (string option in options)
            {
                string[] optionArr = option.Split(':');
                choices.Add(new Dictionary<string, string>() { { "id", optionArr[0] }, { "name", optionArr[1] }, { "color", colors[index++].ToString() } });
            }
            optionDic.Add("choices", choices);
            return optionDic;
        }
        
        private string HandleSDOElement(List<Association> associations, string elemenID)
        {
            var elementAssociation = associations.Find(association => association.Items.Find(item => item.SourceElementID == elemenID) != null);
            if (elementAssociation != null)
            {                
                return "singleSelect";
            }
            return "";
        }

    }
    class CNOElement : CompositeNodeObjectElement
    {
        // 是否支持多选
        public bool filter_isMultiple { get; set; }
        // 下拉选择down、下拉帮助help、下拉树帮助treehelp
        public string filter_inputWay { get; set; }
        public string filter_dataType { get; set; }
        public string filter_dataValue { get; set; }

    }
}
